#include "cpu/exec.h"

void diff_test_skip_qemu();
void diff_test_skip_nemu();

make_EHelper(lidt) {
  // 读取内存中的 Limit 和 Base
  uint16_t limit = vaddr_read(id_dest->addr, 2);
  uint32_t base  = vaddr_read(id_dest->addr + 2, 4);

  // 更新 IDTR
  cpu.idtr.limit = limit;
  cpu.idtr.base  = base;
  print_asm_template1(lidt);
}

make_EHelper(mov_r2cr) {
  switch(id_dest->reg) {
    case 0: 
      cpu.CR0 = id_src->val & 0xFFFFFFFF; 
      break;
    case 3: 
      cpu.CR3 = id_src->val & 0xFFFFF000;
      break;
    default:
      assert(0);
  }
  print_asm("movl %%%s,%%cr%d", reg_name(id_src->reg, 4), id_dest->reg);
}

make_EHelper(mov_cr2r) {
  operand_write(id_dest, &id_src->val);
  print_asm("movl %%cr%d,%%%s", id_src->reg, reg_name(id_dest->reg, 4));

#ifdef DIFF_TEST
  diff_test_skip_qemu();
#endif
}

make_EHelper(int) {
  raise_intr(id_dest->val, decoding.seq_eip);
  print_asm("int %s", id_dest->str);

#ifdef DIFF_TEST
  diff_test_skip_nemu();
#endif
}

make_EHelper(iret) {
  rtl_pop(&decoding.jmp_eip);
  rtl_pop(&cpu.CS);
  rtl_pop(&cpu.eflags.val);
  decoding.is_jmp = 1;
  print_asm("iret");
}

uint32_t pio_read(ioaddr_t, int);
void pio_write(ioaddr_t, int, uint32_t);

make_EHelper(in) {
  uint32_t port = id_src->val;
  int len = id_dest->width;
  uint32_t value = pio_read(port, len);
  rtl_li(&t0, value);
  operand_write(id_dest, &t0);

  print_asm_template2(in);

#ifdef DIFF_TEST
  diff_test_skip_qemu();
#endif
}

make_EHelper(out) {
  uint32_t port = id_dest->val;
  int len = id_src->width;
  uint32_t value = id_src->val;
  
  pio_write(port, len, value);
  print_asm_template2(out);

#ifdef DIFF_TEST
  diff_test_skip_qemu();
#endif
}
